package org.robcash.flexlib.containers
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import mx.containers.Box;
	import mx.controls.Button;

	[DefaultProperty("buttons")]
	
	public class ButtonGroup extends Box
	{
		private var _buttons:Array = [];
		private var childrenChanged:Boolean = false;
		private var _toggleable:Boolean = true;
		private var toggleableChanged:Boolean = true;
		private var _selectedButtonIndices:Array = [];
		private var selectedButtonIndicesChanged:Boolean = false;
		private var _allowMultipleSelections:Boolean = false;
		private var _selectedButtons:Array = [];
		
		public function ButtonGroup()
		{
			super();
		}
		
		// ---------------------------------------------------------
		// Accessor Methods
		// ---------------------------------------------------------

		public function get buttons():Array
		{
			return _buttons;
		}
		
		public function set buttons(value:*):void
		{
			if ( value is Button )
			{
				_buttons = [ value ];
			}
			else
			{
				_buttons = [];
				for each ( var aChild:DisplayObject in value as Array )
				{
					if ( aChild is Button )
					{
						_buttons.push(aChild);
					}
				}
			}
			
			childrenChanged = true;
			invalidateProperties();
		}

		[Bindable]
		[Inspectable(defaultValue="true", category="General")]
		public function get toggleable():Boolean
		{
			return _toggleable;
		}
		
		public function set toggleable(on:Boolean):void
		{
			toggleableChanged = _toggleable == on;
			_toggleable = on;
			if ( toggleableChanged )
			{
				invalidateProperties();
			}
		}
		
		[Bindable("selectedButtonIndicesChanged")]
		[Inspectable(category="General")]
		public function get selectedButtonIndices():Array
		{
			return _selectedButtonIndices;
		}
		
		public function set selectedButtonIndices(indices:Array):void
		{
			_selectedButtonIndices = indices;
			selectedButtonIndicesChanged = true;
			invalidateProperties();
			dispatchEvent(new Event("selectedButtonIndices"));
		}
		
		[Bindable]
		[Inspectable(defaultValue="true", category="General")]
		public function get allowMultipleSelections():Boolean
		{
			return _allowMultipleSelections;
		}
		
		public function set allowMultipleSelections(allowed:Boolean):void
		{
			_allowMultipleSelections = allowed;
		}
		
		[Bindable("selectedButtonsChanged")]
		public function get selectedButtons():Array
		{
			return _selectedButtons;
		}
		
		public function set selectedButtons(buttonList:Array):void
		{
			_selectedButtons = buttonList;
			invalidateProperties();
			dispatchEvent(new Event("selectedButtonsChanged"));
		}
		
		// ---------------------------------------------------------
		// Public Methods
		// ---------------------------------------------------------
		
		// ---------------------------------------------------------
		// Override Methods
		// ---------------------------------------------------------
		
		protected override function commitProperties():void
		{
			super.commitProperties();
			
			if ( childrenChanged )
			{
				childrenChanged = false;
				for each ( var child:Button in buttons )
				{
					addChild(child);
					Button(child).addEventListener(MouseEvent.CLICK, buttonClicked);
					if ( child.selected )
					{
						_selectedButtons.push(child);
					}
				}
			}
			
			if ( selectedButtonIndicesChanged )
			{
				selectedButtonIndicesChanged = false;
				var currentlySelectedButtons:Array = new Array();
				for( var index:int = 0; index < buttons.length; index++ )
				{
					if ( selectedButtonIndices.indexOf(index) >= 0 )
					{
						buttons[index].selected = true;
						currentlySelectedButtons.push(buttons[index]);
					}
					else
					{
						buttons[index].selected = false;
					}
				}
				_selectedButtons = currentlySelectedButtons;
			}
			 
			if ( toggleableChanged )
			{
				toggleableChanged = false;
				for each ( var button:Button in buttons )
				{
					button.toggle = toggleable;
				}
			}
		}
		
		// ---------------------------------------------------------
		// Event Handlers
		// ---------------------------------------------------------
		
		private function buttonClicked(event:MouseEvent):void
		{
			var selectedButton:Button = Button(event.currentTarget);
			
			if ( toggleable && !allowMultipleSelections && selectedButtons[0] == selectedButton )
			{
				// User is attempting to deselect the one remaining selected button.
				// Prevent this from happening.
				event.preventDefault();
				return;
			}
			
			if ( toggleable )
			{
				var currentlySelectedButtons:Array = new Array();
				for each ( var aButton:Button in buttons )
				{
					if ( !allowMultipleSelections && aButton != selectedButton )
					{
						aButton.selected = false;
					}
					
					if ( aButton.selected )
					{
						currentlySelectedButtons.push(aButton);
					}
				}
				
				selectedButtons = currentlySelectedButtons;
			}
		}

	}
}